package solver.moves;

import java.util.Collections;
import java.util.List;
import java.util.Random;

import model.IncrementalCostCalculator;
import model.IncrementalValidator;
import model.MachineSelector;
import model.SolverEnvironment;
import model.Problem;
import model.Solution;

import command.IncrementalMoveProcessToMachineCommand;
import command.Invoker;

public class BestProcessOfMostLoadedMachineToBestMachineMove extends
		SingleProcessOfMostLoadedMachineToBestMachineMove {

	static int max_process_number=30;
	
	public BestProcessOfMostLoadedMachineToBestMachineMove(SolverEnvironment env, MachineSelector ms) {
		super(env,ms);
	}
	
	@Override
	public boolean performMove() {
		int worstMachine = ms.selectMostLoadedMachine(getRandom().nextInt(Math.min(Math.max(getProblem().M/10,1),20))+1);
		Solution pot_sol = env.getPotentialSolution();
		int bestProcess = -1 , bestTargetMachine = -1;
//		long init_cost = env.getCostCalculator().getPotentialSolutionCost();
		long bestCost = Long.MAX_VALUE; 
		int start = worstMachine+1;
		int end =  start+ getProblem().M;
		List<Integer> l1 = getCurrent_solution().getProcessesForMachine(worstMachine);
		Collections.shuffle(l1,env.getRandom());
		int pC=0;
		for (Integer p : l1) {
			int m = testSequentiallyBestNoSchedule(p,worstMachine, start,end); 
			if(m!=-1 && m!=worstMachine){
				long localCost = getCc().getProcessMoveToMachineCost(pot_sol, p, worstMachine, m);
				if(localCost<bestCost){
					bestCost = localCost;
					bestProcess = p;
					bestTargetMachine = m;
				}
			}
			
			if(pC++>max_process_number)
				break;
		}
		
		if(bestProcess !=-1){
			getCc().getProcessMoveToMachineCost(pot_sol,bestProcess, worstMachine, bestTargetMachine);
			makeMove(bestProcess, worstMachine, bestTargetMachine);
			return true;
		}
		else
			return false;
				
	}

}
